#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

#include "src/core/mvc/controller.h"

int Controller::newDocument()
{
  extern Translator translator;
  std::string name = translator.stdString("New workspace", "default new workspace name");
  int wspId = model->addWorkspace(name);

  view->createWidgetForWsp(wspId, name);

  ItemWidget* widget = view->widgetForWsp(wspId);
  model->workspace(wspId).setWidget(widget);

  addLogEntry(LoggerRecord(wspId, LoggerRecord::NewDocument));

  return wspId;
}

#include <QDebug>

void Controller::open(const string& filename)
{
  Parser parser;  // shulga: I strongly dislike a parser that's trying to eat everything and guess what it actually digested

  std::ifstream file(filename.c_str());
  if (file.fail())
  {
    addLogEntry(LoggerRecord(0, LoggerRecord::FileOpenError, filename));
    return;
  }
  char c;
  string contents;
  file.get(c);
  while (file.good())
  {
    contents.push_back(c);
    file.get(c);
  }
  file.close();
  parser.setFile(filename, contents);
  parser.setLogger(this);
  parser.parseFile();
  if (parser.sucessfull())
  {
    int wspId = newDocument();
    if (parser.testContent(Parser::MoleculeContent))
    {
      model->addMolecule(parser.molecule(), wspId);
    }
    if (parser.testContent(Parser::LatticeContent) && !parser.testContent(Parser::FieldContent))
    {
      model->addLattice(parser.lattice(), wspId);
    }
    if (parser.testContent(Parser::FieldContent) && parser.testContent(Parser::LatticeContent))
    {
      const Lattice* l = model->addLattice(parser.lattice(), wspId);
      model->addField(parser.field(), l, wspId);
    }
    addLogEntry(LoggerRecord(wspId, LoggerRecord::FileOpened, filename));
    updateWorkspaceGraphics(wspId);
  }
}

void Controller::updateWorkspaceGraphics(int wspId)
{

  Selection<WorkSpace> selection(&(model->workspace(wspId)));
  SelectionDrawer drawer(selection);
  ProportionalWireframeVisitor wv(model->scene(wspId), model->visitorParameters(), 5.0);
  drawer.DrawMolecule(wv);

/*
  {
    std::ostringstream os;
    Selection<WorkSpace>::atom_sel_type as(selection.atomSelection());
    os << as.size() << " " << as.empty() << std::endl;
    Selection<WorkSpace>::atom_leaf_iterator i = as.obegin(), e=as.oend();
    int j = 0;
    for(;i!=e;i++){
      j++;
      os << i->number() << " ";
    }
    os << "number: " << j;
    addLogEntry(LoggerRecord(0, LoggerRecord::FileOpenError, os.str()));
  }
*/
  /*
  // debug test
  Selection<WorkSpace>::atom_leaf_iterator i = selection.atoms_begin(), e = selection.atoms_end();
  WorkSpace::molecule_const_iterator_type mi = model->workspace(wspId).moleculesBegin();
  container_iterator<Molecule::atom_const_iterator, Molecule> ci(mi->atomsBegin(), *mi);
  Molecule::atom_const_iterator ai = mi->atomsBegin();

  std::ostringstream os;
  os <<  ci->element() << " " << ci->coords().x() << " " << ci->coords().y()<< " " << ci->coords().z() << std::endl;
  os <<  ai->element() << " " << ai->coords().x() << " " << ai->coords().y()<< " " << ai->coords().z() << std::endl;
  ci++; ai++; ci--; ai--;
  os <<  ci->element() << " " << ci->coords().x() << " " << ci->coords().y()<< " " << ci->coords().z() << std::endl;
  os <<  ai->element() << " " << ai->coords().x() << " " << ai->coords().y()<< " " << ai->coords().z() << std::endl;

  const Molecule& m = ci.container();
  Molecule::atom_const_iterator aai = m.atomsBegin();
  aai++;
  os <<  aai->element() << " " << aai->coords().x() << " " << aai->coords().y()<< " " << aai->coords().z() << std::endl;

  typedef container_iterator<Molecule::atom_const_iterator, Molecule> ci_type;
  typedef std::set<ci_type> set_type;
  set_type ss;
  ci++; ci++;
  ss.insert(ci); ci++;
  ss.insert(ci); ci++;
  ss.insert(ci); ci++;
  ss.insert(ci); ci++;
  ss.insert(ci);
  object_iterator<set_type::iterator> oi(ss.begin());
  os <<  oi->element() << " " << oi->coords().x() << " " << oi->coords().y()<< " " << oi->coords().z() << std::endl;

  oi++;
  os <<  oi->element() << " " << oi->coords().x() << " " << oi->coords().y()<< " " << oi->coords().z() << std::endl;
  oi++;
  os <<  oi->element() << " " << oi->coords().x() << " " << oi->coords().y()<< " " << oi->coords().z() << std::endl;
  oi++;
  os <<  oi->element() << " " << oi->coords().x() << " " << oi->coords().y()<< " " << oi->coords().z() << std::endl;

  addLogEntry(LoggerRecord(0, LoggerRecord::FileOpenError, os.str()));
*/  // end of debug

/*
  for (WorkSpace::molecule_const_iterator_type i = model->workspace(wspId).moleculesBegin(), e = model->workspace(wspId).moleculesEnd(); i!=e; ++i )
  {
    MoleculeDrawer drawer(*i, model->visitorParameters(), MoleculeDrawer::custom);
    drawer.drawAll(model->scene(wspId));
//    model->scene(wspId)->update();
  }
*/
  for (WorkSpace::field_iterator_type i = model->workspace(wspId).fieldsBegin(), e = model->workspace(wspId).fieldsEnd(); i!=e; ++i)
  {
    FieldDrawer drawer(*i);
    drawer.drawAll(model->scene(wspId));
//    model->scene(wspId)->update();
  }
  model->scene(wspId)->update();
}

void Controller::save(const int wspId)
{
  view->setWspSaved(wspId);
  addLogEntry(LoggerRecord(wspId, LoggerRecord::DocumentSaved, model->workspace(wspId).name()));
}

void Controller::saveAll()
{

}

void Controller::close(const int wspId)
{
  addLogEntry(LoggerRecord(wspId, LoggerRecord::DocumentClosed, model->workspace(wspId).name()));
  model->removeWorkspace(wspId);
}
